#include "../../PPMC/Modelo.h"
#include <string>
#include <iostream>
#include "../Aritmetico.h"
#include <fstream>

void addSimbolo(Simbolo s, unsigned long frecuencia,
        FrecuenciasSimbolos *frecuencias)
{
    DatoSimboloModelo* dato = new DatoSimboloModelo();
    dato->frecuencia = 1;
    (*frecuencias)[s] = (*dato);
}

FrecuenciasSimbolos* createFrecuencias()
{
    FrecuenciasSimbolos* frecuencias = new FrecuenciasSimbolos();
    for (Simbolo i = 0; i < SimboloEOF +1; i++)
    {
        if ((i % 3) == 0)
        {
            addSimbolo(i, 4l, frecuencias);
        }
        else
        {
            if ((i % 2) == 0)
            {
                addSimbolo(i, 8l, frecuencias);
            }
            else
            {
                addSimbolo(i, (unsigned long) i, frecuencias);
            }
        }
//        addSimbolo(i, 1L, frecuencias);
    }
    return frecuencias;
}

// genera un archivo con todos los caracteres posibles e intenta comprimirlo (lo guarda en el archivo 'comprimido'
void comprimir()
{
    Aritmetico* aritmetico = new Aritmetico();
    ofstream salida;
    salida.open("comprimido");

//	std::ostream& salida = std::cout;
    FrecuenciasSimbolos frecuenciasExcluir;
    FrecuenciasSimbolos frecuencias = (*createFrecuencias());
    aritmetico->comprimir(0, frecuencias, frecuenciasExcluir, salida);
    aritmetico->comprimir(1, frecuencias, frecuenciasExcluir, salida);
    aritmetico->comprimir(2, frecuencias, frecuenciasExcluir, salida);
    aritmetico->comprimir(3, frecuencias, frecuenciasExcluir, salida);
    aritmetico->comprimir(12, frecuencias, frecuenciasExcluir, salida);
    aritmetico->comprimir(167, frecuencias, frecuenciasExcluir, salida);
    aritmetico->comprimir(15, frecuencias, frecuenciasExcluir, salida);
    aritmetico->comprimir(155, frecuencias, frecuenciasExcluir, salida);
    aritmetico->comprimir(51, frecuencias, frecuenciasExcluir, salida);
    aritmetico->comprimir(71, frecuencias, frecuenciasExcluir, salida);
    aritmetico->comprimir(91, frecuencias, frecuenciasExcluir, salida);
    aritmetico->comprimir(111, frecuencias, frecuenciasExcluir, salida);
    aritmetico->comprimir(SimboloEOF, frecuencias, frecuenciasExcluir, salida);
    delete aritmetico;
}

void descomprimir()
{
    Aritmetico* aritmetico = new Aritmetico();
    ifstream entrada;
    entrada.open("comprimido");

//	std::ostream& salida = std::cout;
    FrecuenciasSimbolos frecuenciasExcluir;
    FrecuenciasSimbolos frecuencias = (*createFrecuencias());
    Simbolo s = 0;
// intenta descomprimir el archivo comprimido e imprime los caracteres que descomprime, la salida deberia ser: 1 2 3 ... 256
    while (s != SimboloEOF)
//    for (Simbolo i = 0; i <= SimboloEOF; i++)
    {
        s = aritmetico->descomprimir(frecuencias, frecuenciasExcluir, entrada);
        cout << s << endl;
    }
    delete aritmetico;
}

//cambiar a main para probar y cambiarle el nombre al main original
int test_aritmetico(int argc, char *argv[])
{
    cout << "** comprimir **" << endl;
    comprimir();
    cout << "** descomprimir **" << endl;
    descomprimir();
    return 0;
}
